home *** CD-ROM | disk | FTP | other *** search
/ InterCD 2000 September / september_2000.iso / intercd / root / ^Linux / cfengine-1.5.3 / src / process.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-06-28  |  7.8 KB  |  345 lines

  1. /* cfengine for GNU
  2.  
  3.         Copyright (C) 1995
  4.         Free Software Foundation, Inc.
  5.  
  6.    This file is part of GNU cfengine - written and maintained 
  7.    by Mark Burgess, Dept of Computing and Engineering, Oslo College,
  8.    Dept. of Theoretical physics, University of Oslo
  9.  
  10.    This program is free software; you can redistribute it and/or modify it
  11.    under the terms of the GNU General Public License as published by the
  12.    Free Software Foundation; either version 2, or (at your option) any
  13.    later version.
  14.  
  15.    This program is distributed in the hope that it will be useful,
  16.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.    GNU General Public License for more details.
  19.  
  20.   You should have received a copy of the GNU General Public License
  21.   along with this program; if not, write to the Free Software
  22.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA
  23.  
  24. */
  25.  
  26.  
  27. /*******************************************************************/
  28. /*                                                                 */
  29. /* Process handling                                                */
  30. /*                                                                 */
  31. /*******************************************************************/
  32.  
  33.  
  34. #include "cf.defs.h"
  35. #include "cf.extern.h"
  36.  
  37. int DEADLOCK = false;
  38. FILE *PIPE;
  39.  
  40. /*******************************************************************/
  41.  
  42. LoadProcessTable(procdata,psopts)
  43.  
  44. struct Item **procdata;
  45. char *psopts;
  46.  
  47. { FILE *pp;
  48.   char pscomm[maxlinksize];
  49.  
  50. sprintf(pscomm,"%s %s",VPSCOMM[VSYSTEMHARDCLASS],psopts);
  51.  
  52. Verbose("%s: Running process command %s\n",VPREFIX,pscomm); 
  53.   
  54. if ((pp = cfpopen(pscomm,"r")) == NULL)
  55.    {
  56.    sprintf(OUTPUT,"Couldn't open the process list with command %s\n",pscomm);
  57.    CfLog(cferror,OUTPUT,"popen");
  58.    return false;
  59.    }
  60.  
  61. while (!feof(pp))
  62.    {
  63.    ReadLine(VBUFF,bufsize,pp);
  64.    AppendItem(procdata,VBUFF,"");
  65.    }
  66.  
  67. cfpclose(pp);
  68. return true;
  69. }
  70.  
  71. /*******************************************************************/
  72.  
  73. DoProcessCheck(pp,procdata)
  74.  
  75. struct Process *pp;
  76. struct Item *procdata;
  77.  
  78. { struct Item *ip, *ip2;
  79.   char *err, line[bufsize], *sp;
  80.   int match, pid=-1, ret, matches=0, got;
  81.   int BreakPipe();
  82.   FILE *pipe;
  83.   regex_t rx,rxcache;
  84.   regmatch_t pmatch;
  85.   size_t nmatch = 1;
  86.   pid_t cfengine_pid = getpid();
  87.   
  88. Debug2("Looking for process %s\n",pp->expr);
  89.  
  90. if (regcomp(&rxcache,pp->expr,REG_EXTENDED) != 0)
  91.    {
  92.    sprintf(OUTPUT,"Regular expression error for process pattern %s\n",pp->expr);
  93.    CfLog(cferror,OUTPUT,"");
  94.    sprintf(OUTPUT,"%s\n",err);
  95.    CfLog(cferror,OUTPUT,"");
  96.    return;
  97.    }
  98.  
  99. for (ip = procdata; ip != NULL; ip=ip->next)
  100.    {
  101.    bcopy(&rxcache,&rx,sizeof(rx)); /* To fix a bug on some implementations where rx gets emptied */
  102.    if (regexec(&rx,ip->name,1,&pmatch,0) == 0)
  103.       {
  104.       pid = -1;
  105.       got = true;
  106.       
  107.       for (ip2 = pp->inclusions; ip2 != NULL; ip2 = ip2->next)
  108.      {
  109.      got = false;
  110.      
  111.      if (strstr(ip->name,ip2->name))
  112.         {
  113.         got = true;
  114.         break;
  115.         }
  116.      }
  117.       
  118.       if (!got)
  119.      {
  120.      continue;
  121.      }
  122.       
  123.       got = false;
  124.       
  125.       for (ip2 = pp->exclusions; ip2 != NULL; ip2 = ip2->next)
  126.      {
  127.      if (strstr(ip->name,ip2->name))
  128.         {
  129.         got = true;
  130.         break;
  131.         }
  132.      }
  133.       
  134.       if (got)
  135.      {
  136.      continue;
  137.      }
  138.       
  139.       for (sp = ip->name; *sp != '\0'; sp++) /* if first field contains alpha, skip */
  140.      {
  141.      while (true)
  142.         {
  143.         while (!isdigit(*sp) && (*sp != '\0'))
  144.            {
  145.            sp++;
  146.            }
  147.         
  148.         if ((sp > ip->name) && isalnum(*(sp-1))) /* Username contains number*/
  149.            {
  150.            sp++;
  151.            }
  152.         else
  153.            {
  154.            break;
  155.            }
  156.         }
  157.      
  158.      sscanf(sp,"%d",&pid);
  159.      
  160.      if (pid != -1)
  161.         {
  162.         break;
  163.         }
  164.      }  
  165.       
  166.       if (pid == -1)
  167.      {
  168.      sprintf(OUTPUT,"Unable to extract pid while looking for %s\n",pp->expr);
  169.      CfLog(cfverbose,OUTPUT,"");
  170.      continue;
  171.      }
  172.       
  173.       Debug2("Found matching pid %d\n",pid);
  174.       
  175.       matches++;
  176.       
  177.       if (pid == 1 && pp->signal == cfhup)
  178.      {
  179.      Verbose("(Okay to send HUP to init)\n");
  180.      }
  181.       else if (pid < 4)
  182.      {
  183.      Verbose("%s: will not signal or restart processes 0,1,2,3\n",VPREFIX);
  184.      Verbose("%s: occurred while looking for %s\n",VPREFIX,pp->expr);
  185.      continue;
  186.      }
  187.       
  188.       if (pp->action == 'w')
  189.      {
  190.      sprintf(OUTPUT,"Process warning, found: %s\n",ip->name);
  191.      CfLog(cfinform,OUTPUT,"");
  192.      continue;
  193.      }
  194.       
  195.       if (pp->signal != cfnosignal)
  196.      {
  197.      sprintf(OUTPUT,"Signalling process %d (%s) with %s\n",pid,pp->expr,SIGNALS[pp->signal]);
  198.      CfLog(cfinform,OUTPUT,"");
  199.      
  200.      if (!DONTDO)
  201.         {
  202.         if (pid == cfengine_pid)
  203.            {
  204.            CfLog(cfverbose,"Cfengine will not kill itself!\n","");
  205.            }
  206.         else if ((ret = kill((pid_t)pid,pp->signal)) < 0)
  207.            {
  208.            sprintf(OUTPUT,"Couldn't send signal to pid %d\n",pid);
  209.            CfLog(cfverbose,OUTPUT,"kill");
  210.            
  211.            continue;
  212.            }
  213.         
  214.         if ((pp->signal == cfkill || pp->signal == cfterm) && ret >= 0)
  215.            {
  216.            sprintf(OUTPUT,"Killed: %s\n",ip->name);
  217.            CfLog(cfinform,OUTPUT,"");
  218.            }
  219.         }
  220.      }
  221.       }
  222.    }
  223.  
  224. if (matches > 0)
  225.    {
  226.    Verbose("Defining classes %s\n",pp->defines);
  227.    AddMultipleClasses(pp->defines);
  228.    }
  229.  
  230. if (pp->matches >= 0)
  231.    {
  232.    switch (pp->comp)
  233.       {
  234.       case '=': if (matches != (int)pp->matches)
  235.                    {
  236.                sprintf(OUTPUT,"%d processes matched %s (should be %d)\n",matches,pp->expr,pp->matches);
  237.            CfLog(cferror,OUTPUT,"");
  238.            }
  239.                 break;
  240.         
  241.       case '>': if (matches < (int)pp->matches)
  242.                {
  243.                sprintf(OUTPUT,"%d processes matched %s (should be >=%d)\n",matches,pp->expr,pp->matches);
  244.            CfLog(cferror,OUTPUT,"");
  245.                } 
  246.                 break;
  247.         
  248.       case '<': if (matches > (int)pp->matches)
  249.                {
  250.                sprintf(OUTPUT,"%d processes matched %s (should be <=%d)\n",matches,pp->expr,pp->matches);
  251.            CfLog(cferror,OUTPUT,"");
  252.                } 
  253.       }
  254.    }
  255.  
  256. if (strlen(pp->restart) != 0)
  257.    {
  258.    if ((matches != 0) && (pp->signal != cfkill) && (pp->signal != cfterm))
  259.       {
  260.       Verbose("%s: Matches found for %s - no restart sequence\n",VPREFIX,pp->expr);
  261.       regfree(&rx);
  262.       return;
  263.       }
  264.    
  265.    sprintf(OUTPUT,"Executing shell command: %s\n",pp->restart);
  266.    CfLog(cfinform,OUTPUT,"");
  267.  
  268.    if (DONTDO)
  269.       {
  270.       regfree(&rx);
  271.       return;
  272.       }
  273.  
  274.    if (pp->useshell == 'y')
  275.       {
  276.       if ((PIPE = popen(pp->restart,"r")) == NULL)
  277.      {
  278.      sprintf(OUTPUT,"Process restart execution failed on %s\n",pp->restart);
  279.      CfLog(cferror,OUTPUT,"popen");
  280.      regfree(&rx);
  281.      return;
  282.      }
  283.       }
  284.    else
  285.       {
  286.       if ((PIPE = cfpopen(pp->restart,"r")) == NULL)
  287.      {
  288.      sprintf(OUTPUT,"Process restart execution failed on %s\n",pp->restart);
  289.      CfLog(cferror,OUTPUT,"popen");
  290.      regfree(&rx);
  291.      return;
  292.      }
  293.       }
  294.  
  295.    DEADLOCK = false;   
  296.    
  297.    while (!feof(PIPE))
  298.       {
  299.       if (pp->useshell == 'd') /* dumb shell */
  300.      {
  301.      fgets(line,1,PIPE);
  302.          break;
  303.      }
  304.       
  305.       ReadLine(line,bufsize,PIPE);
  306.  
  307.       if (feof(PIPE) || ferror(PIPE))
  308.      {
  309.      break;
  310.      }
  311.       
  312.       if (strstr(line,"cfengine-die"))
  313.      {
  314.      break;
  315.      }
  316.  
  317.       /* patch for ERESTARTSYSTEM bug in popen */
  318.  
  319.       if (strstr(line,"cfd: start") || DEADLOCK)
  320.      {
  321.          printf("");
  322.      break;
  323.      }
  324.       
  325.       sprintf(OUTPUT,"Restart: %s",line);
  326.       CfLog(cfinform,OUTPUT,"");
  327.       }
  328.  
  329.    if (pp->useshell == 'y')
  330.       {
  331.       pclose(PIPE);
  332.       }
  333.    else
  334.       {
  335.       cfpclose(PIPE);
  336.       }
  337.    
  338.    sprintf(OUTPUT,"(Done with %s)\n",pp->restart);
  339.    CfLog(cfinform,OUTPUT,"");
  340.    }
  341.  
  342. regfree(&rx);
  343. }
  344.  
  345.